﻿using System;

namespace CommonServiceManager.Configuration
{
	/// <summary>
	/// The service that makes our different project parts configurable for Dependency Injection and Inversion of Control.
	/// </summary>
	public interface IServiceConfigurator
	{
		/// <summary>
		/// Access to DI configure a type <typeparamref name="TToConfigure"/>
		/// </summary>
		/// <typeparam name="TToConfigure">The implementation to configure.</typeparam>
		/// <param name="implementationKey">The key when configuring multiple implementations of the same contract.</param>
		/// <returns>A <see cref="IConfigurator{TToConfigure}"/> that enables further configuration on the <typeparamref name="TToConfigure"/></returns>
		/// <exception cref="ConfigurationException">if there is are errors configuring the <typeparamref name="TToConfigure"/>.</exception>
		IConfigurator<TToConfigure> Configure<TToConfigure>(string implementationKey = null);

		/// <summary>
		/// Register a <typeparamref key="TImplementation"/> as implementing <typeparamref key="TContract"/>.
		/// </summary>
		/// <typeparam name="TContract">The contract to register as a service.</typeparam>
		/// <typeparam name="TImplementation">The implementation that supports this contract.</typeparam>
		/// <param name="implementationKey">The key when registering multiple implementations of the same contract.</param>
		/// <returns>A <see cref="IConfigurator{TImplementation}"/> that enables further configuration on the <typeparamref key="TImplementation"/></returns>
		/// <exception cref="ConfigurationException">if there is are errors configuring the <typeparamref name="TImplementation"/>.</exception>
		IConfigurator<TImplementation> RegisterType<TContract, TImplementation>(string implementationKey = null)
			where TImplementation : TContract;

		/// <summary>
		/// Register an instance of <typeparamref key="TContract"/> as the (shared) service that supports this contract
		/// </summary>
		/// <typeparam name="TContract">The contract to register as a service.</typeparam>
		/// <param name="implementationKey">The key when registering multiple implementations of the same contract.</param>
		/// <param name="instance">The instance of <typeparamref key="TContract"/> to register</param>
		/// <exception cref="ConfigurationException">if there is are errors configuring the <typeparamref name="TContract"/>.</exception>
		void RegisterInstance<TContract>(TContract instance, string implementationKey = null);

		/// <summary>
		/// Register an instance of <paramref key="instance"/> as the (shared) service that supports this contract
		/// </summary>
		/// <param name="instance">The instance of <paramref key="instance"/> to register</param>
		/// <param name="contractType">The type to register as.</param>
		/// <param name="implementationkey">The key when registering multiple implementations of the same contract.</param>
		/// <exception cref="ConfigurationException">if there is are errors configuring the <paramref name="contractType"/>.</exception>
		void RegisterInstance(object instance, Type contractType, string implementationkey = null);
	}
}